use std::cmp::Ordering;
use std::ops;
use std::sync::LazyLock;

static POLICY:LazyLock<Vec<(i32, i32,Policy)>>=LazyLock::new(||
    vec![
    (1970,2025,Policy{
        g55: TargetAge::G55(Role::new_n(55)),
        g50: TargetAge::G50(Role::new_n(50)),
        b60: TargetAge::B60(Role::new_n(60)),
    }),
    (2025,2040,Policy{
        g55: TargetAge::G55(Role::new_m(4)),
        g50: TargetAge::G50(Role::new_m(2)),
        b60: TargetAge::B60(Role::new_m(4)),
    }),
    (2040,3000,Policy{
        g55: TargetAge::G55(Role::new_n(58)),
        g50: TargetAge::G50(Role::new_n(55)),
        b60: TargetAge::B60(Role::new_n(63)),
    }),

    ]);
#[derive(Clone, Copy)]
enum TargetAge {
    G55(Role),
    G50(Role),
    B60(Role),
}
struct Policy{
    g55:TargetAge,
    g50:TargetAge,
    b60:TargetAge,
}
#[derive(Clone, Copy)]
enum Role {
    MonthDealy(i32),
    Old(i32)
}
#[derive(Clone, Copy,Debug)]
struct YearMonth {
    year:i32,
    month:i32
}
pub fn retire_time(time: &str, tp: &str) -> String {
    // 解析输入的出生日期
    let time=time.split_once('-').unwrap();
    let birth= YearMonth::new(time.0.parse().unwrap(),time.1.parse().unwrap());
    let mut tui =birth.clone();
    let mut add =0;
    // 原法定退休年龄
    let target_age = match tp {
        "原法定退休年龄55周岁女职工" => 55,
        "原法定退休年龄50周岁女职工" => 50,
        "男职工" => 60,
        _ => panic!("Invalid role"),
    };
    for p in POLICY.iter(){
        let policy;
        match target_age{
            50=>{
                policy=p.2.g50;
            }
            55=>{
                policy=p.2.g55;
            }
            60=>{
                policy=p.2.b60;
            }
            _=>panic!("Invalid target age")
        }
        match policy.count(&birth,&mut tui,p.0,p.1,&mut add) {
            None => {}
            Some(a) => {
                return format!("{}-{:02},{2:.3$},{4}", a.0.year, a.0.month,a.1,
                               if (a.1- (a.1 as u32)as f32) >0.009{
                                   2
                               }
                               else{
                                   0
                               }
                    ,a.2);
            }
        }

    }
    panic!("")
}
impl YearMonth{
    fn new(birth_year:i32,birth_month:i32)->Self{
        Self{
            year:birth_year,
            month:birth_month
        }
    }
}
impl TargetAge{
    fn count(&self, birth: &YearMonth, tui: &mut YearMonth,start_year:i32,end_year:i32,add:&mut i32) -> Option<(YearMonth,f32,i32)> {
        match self{
            TargetAge::G55(r)|
            TargetAge::G50(r)|
            TargetAge::B60(r)
            => {
                match r{
                    Role::MonthDealy(m) => {
                        let mut tui =tui.clone();
                        let mut month = tui.month.clone()+(tui.year.clone()-start_year)*12;
                        let mut a=1;
                        let max= ((end_year-start_year)*12)/(m+1);
                        tui=tui+1;
                        while month>*m {
                            month-=*m;
                            tui=tui+1;
                            a+=1;
                            if tui>= YearMonth::new(end_year-(end_year-start_year)/m, end_year-((end_year-start_year)*12)/m) {
                                *add=max;
                                return None
                            }
                        };
                        *add+=a;
                        Some((tui.clone(),tui.count_old(birth.clone()) , *add))
                    }
                    Role::Old(o) => {
                        *tui=YearMonth::new(birth.year + o, birth.month);
                        if *tui < YearMonth::new(end_year, 0){
                            return Some((tui.clone(), tui.count_old(birth.clone()), *add));
                        }
                        None
                    }
                }
            }

        }
    }
}

impl YearMonth{
    fn count_old(self,birth:YearMonth)->f32{
        (((self.year-birth.year)*12)+(self.month-birth.month)) as f32/12.0
    }
}
impl Eq for YearMonth {}

impl PartialEq<Self> for YearMonth {
    fn eq(&self, other: &Self) -> bool {
        self.year == other.year && self.month == other.month
    }
}

impl PartialOrd<Self> for YearMonth {
    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
        Some(self.cmp(other))
    }
}

impl Ord for YearMonth {
    fn cmp(&self, other: &Self) -> Ordering {
        if self.year == other.year{
            if self.month == other.month{
                Ordering::Equal
            }
            else if self.month < other.month{
                Ordering::Less
            }
            else {
                Ordering::Greater
            }
        }
        else if self.year < other.year{
            Ordering::Less
        }
        else{
            Ordering::Greater

        }
    }
}
impl ops::Add<i32> for YearMonth {
    type Output = YearMonth;

    fn add(self, rhs: i32) -> Self::Output {
        YearMonth::new(self.year+(self.month+rhs-1)/12,(self.month+rhs-1)%12+1)
    }
}




impl Role{
    fn new_m(delay:i32)->Self{
        Self::MonthDealy(delay)
    }
    fn new_n(old:i32)->Self{
        Self::Old(old)
    }
}